package com.easygoods.service;

import com.bestvike.stone.core.lang.RandomUtils;
import com.bestvike.stone.core.lang.StringUtils;
import com.bestvike.stone.spring.exception.BusinessException;
import com.bestvike.stone.spring.exception.ErrorCode;
import com.bestvike.stone.spring.redis.RedisUtils;
import com.bestvike.stone.spring.service.BaseService;
import com.bestvike.stone.spring.shiro.authz.exception.authz.UnauthorizedException;
import com.easygoods.enums.Channel;
import com.easygoods.external.sms.SmsApi;
import com.easygoods.external.sms.SmsProperties;
import com.easygoods.request.ChangeMobileBySmsRequest;
import com.easygoods.request.ChangePayPwdBySmsRequest;
import com.easygoods.request.ExternalRegisterRequest;
import com.easygoods.request.SendRegisterSmsRequest;
import com.easygoods.shiro.auth.UserAuth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Created by 许崇雷 on 2018-12-26.
 */
@Service
public class SmsService extends BaseService {
    private static final int CODE_LEN = 6;//验证码长度
    private static final String REGISTER_TEMPLATE = "SMS_153910181";//注册短信模版编号
    private static final String CHANGE_PAY_PWD_TEMPLATE = "SMS_162522605";//修改支付密码短信模版编号
    private static final String CHANGE_MOBILE_TEMPLATE = "SMS_162547419";//修改绑定手机号短信模版编号
    private static final String CODE_NAME = "code";//模版参数名
    private static final String SMS_FORMAT = "SMS:%s:%s";
    @Autowired
    private SmsApi smsApi;
    @Autowired
    private SmsProperties smsProperties;

    //生成短信验证码
    private static String genVerifyCode() {
        StringBuilder stringBuilder = new StringBuilder(CODE_LEN);
        for (int i = 0; i < CODE_LEN; i++)
            stringBuilder.append(RandomUtils.nextInt(0, 10));
        return stringBuilder.toString();
    }

    //发送验证类验证码
    private void sendVerifySms(Channel channel, String openId, String mobile, String templateCode) {
        String verifyCode = genVerifyCode();
        Map<String, String> templateParam = new HashMap<>(1);
        templateParam.put(CODE_NAME, verifyCode);
        this.smsApi.sendSmsByUser(channel, openId, mobile, templateCode, templateParam);
        RedisUtils.set(String.format(SMS_FORMAT, templateCode, mobile), verifyCode, this.smsProperties.getValidTime().getSeconds(), TimeUnit.SECONDS);
    }

    //校验验证类验证码
    private void checkVerifySms(String mobile, String templateCode, String verifyCode) {
        final String redisCode = RedisUtils.get(String.format(SMS_FORMAT, templateCode, mobile), String.class);
        if (StringUtils.isBlank(redisCode) || !StringUtils.equals(verifyCode, redisCode))
            throw new BusinessException(ErrorCode.ERROR_SERVER, "验证码错误");
    }

    //发送注册验证码
    public void sendRegisterSms(SendRegisterSmsRequest request) {
        if (!AuthService.hasOpenId(request.getChannel(), request.getOpenId())) //验证 openId 是否有效,防止被刷
            throw new UnauthorizedException();
        this.sendVerifySms(request.getChannel(), request.getOpenId(), request.getMobile(), REGISTER_TEMPLATE);
    }

    //验证注册验证码
    public void checkRegisterSms(ExternalRegisterRequest request) {
        if (!AuthService.hasOpenId(request.getChannel(), request.getOpenId())) //验证 openId 是否有效,防止被刷
            throw new UnauthorizedException();
        this.checkVerifySms(request.getMobile(), REGISTER_TEMPLATE, request.getVerifyCode());
    }

    //发送修改支付密码验证码
    public void sendChangePayPwdSms() {
        final UserAuth auth = this.getAuth();
        this.sendVerifySms(null, auth.getMemberId(), auth.getMobile(), CHANGE_PAY_PWD_TEMPLATE);
    }

    //验证修改支付密码验证码
    public void checkChangePayPwdSms(ChangePayPwdBySmsRequest request) {
        final UserAuth auth = this.getAuth();
        this.checkVerifySms(auth.getMobile(), CHANGE_PAY_PWD_TEMPLATE, request.getVerifyCode());
    }

    //发送修改手机号验证码
    public void sendChangeMobileSms() {
        final UserAuth auth = this.getAuth();
        this.sendVerifySms(null, auth.getMemberId(), auth.getMobile(), CHANGE_MOBILE_TEMPLATE);
    }

    //验证修改手机号验证码
    public void checkChangeMobileSms(ChangeMobileBySmsRequest request) {
        final UserAuth auth = this.getAuth();
        this.checkVerifySms(auth.getMobile(), CHANGE_MOBILE_TEMPLATE, request.getVerifyCode());
    }
}
